4W - 실리움 로드밸런서 기능 - 서비스 IP, L2
개요
이 노트에서는 로드 밸런서 서비스에 대한 실리움의 기능들을 소개한다.
네트워크에서 로드밸런서는 트래픽을 분산하는 물리적 장치, 소프트웨어를 말한다.
그러나 쿠버네티스에서는 로드밸런서라는 별도의 추상화된 개념을 두고 있는데, 구체적으로는 서비스의 로드밸런서 유형이다.
쿠버네티스에 대한 개념을 알고 있는 독자를 대상으로 하기에 관련한 설명은 생략하고자 한다.
Metal LB
실리움이 제공하는 로드밸런서 기능은 사실 MetalLB에서 사용하는 방식을 기본적으로 활용한다.
그렇기에 실리움을 알아보기 전에 간단하게 메탈 LB가 무얼 하는지 간단하게 짚어보자.
bareMetal LoadBalancer.[^1]
쿠버네티스의 서비스 로드밸런서는 보통 클라우드 공급자가 제공해주는 외부의 로드밸런서를 활용해야만 한다.
외부의 로드밸런서와 내부의 서비스를 연동하여 트래픽을 전달해주는 방식인 것이다.
그래서 이 연동을 도와주는 로드밸런서 컨트롤러 프로세스를 띄우는 게 보통이며, 대표적으로 AWS Load Balancer Controller를 예로 들 수 있다.
이러한 방식은 필연적으로 클러스터 관리가 외부의 로드밸런서 벤더에 일부 종속되게 하여 중립성을 해친다는 아쉬운 지점을 야기한다.
그럼 클러스터 내부에서의 설정만을 통해 외부의 장비에 로드밸런싱 경로를 세팅하게 만들 순 없는 걸까?
이러한 요구는 특히 온프레미스 환경에서 대두됐고, 이에 메탈 LB가 개발됐다.
메탈 LB는 기본적인 네트워크 프로토콜을 활용해 같은 LAN 내, 혹은 라우터에 클러스터를 위한 엔드포인트를 노출하여 트래픽 경로가 알아서 설정되게끔 만들어준다.
이게 없었다면 온프레미스에서는 그저 노드포트를 노출시켜서 서비스하거나, 앞단에 추가 장비를 두어 포트포워딩을 해야만 원하는 포트로 트래픽을 노출할 수 있었을 것이다.
기능
메탈 LB가 하는 기능은 크게 두 가지인데, 웬만한 로드밸런서 컨트롤러가 하는 일이라 보면 된다.
- 주소 할당(Address Allocation) - 더 크게는 IPAM이라고도 부른다.
- 가상의 IP 대역을 로드밸런서에 부여하는 작업.
- 외부 전파(External Announcement)
- 부여한 IP로 외부에서 트래픽을 전송할 수 있는 방법을 마련해야 한다.
- 이 IP를 쓸 수 있는 상태라고 전파하는 과정이라고도 할 수 있다.
- 이때 표준 프로토콜인 ARP, NDP(ipv6의 arp)나 BGP를 사용한다.
보통 로드 밸런서는 클러스터 외부에서 클러스터와 관련 없는 외부 IP를 할당한 뒤에 이를 클러스터에 알려만 준다.
그러나 메탈 LB는 클러스터 내부에 있으므로 사용되지 않고 있는 임의의 IP 대역을 관리자가 설정하여 로드밸런서 IP 대역으로 활용해야 한다.
그 후에는 실제로 이 IP로 트래픽이 흘러갈 수 있도록, 이 IP로 가려면 어떻게 해야 하는지 알리는 작업을 해야 하는데 이것이 외부 전파이다.
참고로 실리움에서는 각 기능을 조금 더 확장해서 제공해주고 있다.
외부 전파 - Layer2 모드
ip 주소를 할당하는 작업은 꽤나 간단하게 일어나고, 외부 전파 방식 두 가지를 간단하게 알아보자.
가시다님 스터디에서 공유된 자료.
첫번째는 layer 2의 arp를 활용하는 모드로, 같은 네트워크 안에 있는 호스트가 클러스터에 접근 가능하게 해주는 모드이다.
로드밸런서를 만들면 스피커 파드 중 한 노드에 위치한 녀석이 리더가 된다.
리더 스피커는 자신의 노드가 해당 트래픽을 감당할 수 있는 곳이라고 garp(Gratituous ARP, 자신을 드러내는 방식)를 같은 네트워크에 뿌린다.
그 덕분에 이 전파를 들은 호스트에서 서비스의 외부 ip로 트래픽을 날리면 리더 스피커가 있는 노드로 트래픽이 가게 된다.
그러면 이 노드의 iptables로 트래픽을 엔드포인트로 나누는 구조이다.
그래서 이건 사실 로드밸런서라기 보다는.. 리더 노드가 죽었을 때 다른 노드를 선출하는 그냥 장애 회복 매커니즘의 로직이 핵심이라고 문서에 나온다.
이 방식의 문제는 스피커 파드가 있는 노드로 트래픽이 몰리니 한 노드에 병목이 심할 가능성이 높다.
그래서 실질적으로는 로드밸런서라고 하기 좀 그렇다..
그리고 무엇보다 L2 레벨에서 광고를 하는 것이기 때문에 LAN 바깥으로 나가는 것이 불가능하다.
(이전에 배운 vxlan, geneve 등과 결합해 활용할 순 있겠다.)
외부전파 - BGP 모드
BGP를 사용하는 방식으로 외부의 L3 스위치를 사용하여 진정한 의미의 로드밸런싱을 수행한다.
우리 AS와 라우터 AS, IP를 입력하면 BGP로 외부 라우터에 해당 IP에 대해 클러스터의 노드들을 광고한다.
그럼 외부 라우터가 ECMP(Equal Cost Multi Path, 같은 비용에 대해 다중 경로 채택)를 통해 트래픽을 분산해준다.
bgp가 뭔지는 다음 주차에서 조금 더 자세하게 다루겠다.
실리움 로드밸런서 실습
이론적인 설명은 메탈 LB 선에서 끝났고, 바로 실습을 하면서 실리움의 기능들을 확인해보도록 한다.
실습 환경은 이전 문서와 동일하며, 이전 실습을 따라왔다면 라우팅 모드는 geneve로 되어 있을 것이다.
로드밸런서 서비스 IPAM
먼저 실리움은 로드밸런서 서비스가 받을 임의의 IP 대역을 관리하는 IPAM 기능을 제공한다.[^5]
위에서 본 Metal LB가 기본으로 가진 기능과 마찬가지인 격이다.
당연히 실제로 외부에서 접근하기 위해서는 외부 전파 방식을 세팅해야 하며, 이걸로 로드밸런서를 쓸 수 있게 되는 건 아니다.
문서를 보면 설정할 수 있는 옵션이 꽤 다양하다.
apiVersion: "cilium.io/v2"
kind: CiliumLoadBalancerIPPool
metadata:
name: "cilium-lb-pool"
spec:
blocks:
- start: "192.168.10.211"
stop: "192.168.10.215"
- cidr: "192.168.30.00/24"
# 옵션. cidr를 받을 서비스를 한정지어버릴 수도 있다.
serviceSelector:
matchLabels:
color: red
# disabled: true
kubectl get ippools
만들고 나서 확인하면 사용 가능한 상태인지, 충돌되는 IP는 없는지 등의 정보가 출력된다.
새로 만든 풀이 기존 풀과 겹치면 충돌이 표시될 것이다.
만든 풀을 바로 사용해본다.
kubectl patch svc webpod -p '{"spec":{"type":"LoadBalancer"}}'
k label svc webpod color=red
kubectl get svc webpod
위의 설정에서 특정 라벨을 기반으로 서비스를 매칭하도록 설정했다.
그래서 해당 라벨을 붙여주어야만 IP를 할당 받을 수 있다.
로드 밸런서 유형에 대해 알고 있다면 너무도 당연한 내용으로, 현재 저 IP는 클러스터 내부에서는 활용할 수 있다.
LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
kubectl exec -it curl-pod -- curl -s $LBIP
vagrant ssh k8s-ctr -c "curl -s $LBIP"
while true; do kubectl exec -it curl-pod -- curl -s $LBIP | grep Hostname; sleep 0.1; done
for i in {1..100}; do kubectl exec -it curl-pod -- curl -s $LBIP | grep Hostname; done | sort | uniq -c | sort -nr
IP 하나를 일부러 충돌나게 스펙을 만들어서 적용하자 바로 충돌이 난다고 표시된다.
기본적으로 ip 풀은 먼저 만들어진 것이 우선권을 가진다.
테스트 하는 김에 서비스를 만들 때 아예 IP를 요청하는 실습도 해보자.[1]
apiVersion: v1
kind: Service
metadata:
name: exact-ip
labels:
color: red
annotations:
"lbipam.cilium.io/ips": "192.168.10.215"
spec:
selector:
app: exact-ip
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
스펙은 대충 작성하고, 일부러 충돌이 난 IP 부분을 설정했다.
먼저 만들어진 IP 풀에서 ip를 받는 것을 확인할 수 있다.
충돌나라고 만든 풀에서 ip를 받으려고 요청 IP를 수정하자, IP를 부여받지 못했다.
충돌이 난 IP 풀은 통째로 사용할 수 없도록 되어있는 것으로 보인다.
이 방식이 당연하다 생각하긴 하지만 available을 표시해둬서 순간 사용할 수 있는 건 줄..
L2 광고
이제 만들어진 IP를 외부에서 접근할 수 있게 알리는 일만 남았다.
외부 전파 방식 중 하나인 L2 광고부터 보도록 하자.[2]
helm upgrade cilium cilium/cilium --namespace kube-system --version 1.18.0 --reuse-values \
--set l2announcements.enabled=true
kubectl rollout restart -n kube-system ds/cilium
상태를 확인해본다.
kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg config --all | grep EnableL2Announcements
cilium config view | grep enable-l2
그러나 아직은 아래 요청들은 수행되지 않는다.
# 라우터에서
arping -i eth1 $LBIP -c 100000
curl 192.168.10.211
실제로 IP를 광고하기 위해서는 어디로 광고할지를 나타내는 커스텀 리소스를 생성해야 한다.
apiVersion: "cilium.io/v2alpha1" # pod ip pool과 더불어 이놈만 아직 alpha 단계이다.
kind: CiliumL2AnnouncementPolicy
metadata:
name: policy1
spec:
serviceSelector:
matchLabels:
app: webpod
nodeSelector:
matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s-w0
interfaces:
- ^eth[1-9]+
externalIPs: true
loadBalancerIPs: true
어떤 서비스에 대해 어떤 노드를 리더로 삼을 거고, 어떤 인터페이스로 광고할 건지 설정하는 것을 볼 수 있다.
다른 대역 노드 리더가 잡혀서 에러가 발생하지 않게 노드를 한정지었다.
정책이 만들어지면 그 순간부터 바로 garp가 시작되고, 해당 내용을 확인할 수 있게 된다.
arp로 ip와 맥 주소가 매칭되니 트래픽을 날려 통신도 가능해진다.
이제 해당 정보는 arp 테이블에 기록된다.
실리움은 리더 선출과 관리를 위해 lease 리소스를 사용한다.
lease 리소스는 굉장히 경량이고 갱신을 빠르게 할 수 있어 리더 관리에 매우 유용하여 자주 쓰이는 것 같다.
각 실리움 에이전트에서 자신 노드에서 광고하는 것을 확인할 때는 아래처럼 할 수 있다.
# cilium 파드 이름 지정
export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-ctr -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD1=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w1 -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD2=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w0 -o jsonpath='{.items[0].metadata.name}')
echo $CILIUMPOD0 $CILIUMPOD1 $CILIUMPOD2
# 현재 해당 IP에 대한 리더가 위치한 노드의 cilium-agent 파드 내에서 정보 확인
kubectl exec -n kube-system $CILIUMPOD0 -- cilium-dbg shell -- db/show l2-announce
kubectl exec -n kube-system $CILIUMPOD1 -- cilium-dbg shell -- db/show l2-announce
kubectl exec -n kube-system $CILIUMPOD2 -- cilium-dbg shell -- db/show l2-announce
kubectl -n kube-system logs ds/cilium | grep "l2"
결론
메탈 LB의 모든 기능을 실리움이 흡수했기 때문에 온프레미스 환경에서 실리움을 사용한다면 관리 포인트를 통합시킬 수 있다는 점에서 큰 이점이 있겠다.
L2 모드 자체는 굉장히 간단하게 설정이 가능하다는 점에서는 유용하지만 테스트 설정을 할 때 봤듯이 LAN을 벗어나지 못하기에 그만큼 한계도 뚜렷하다.
다음 주차에 보게 될 BGP는 동적 라우팅 프로토콜로서 라우터에 설정을 넣고, 라우터가 직접 경로를 제시해준다.
그래서 외부 라우터로 경로를 전파하는 것도 가능하고 라우팅을 건드리기 때문에 이전에 봤던 네이티브 라우팅 모드에도 활용될 수 있다.
시간 나면 DSR 기능을 조금 테스트해보고 싶다.[3]
이전 글, 다음 글
다른 글 보기
이름 | index | noteType | created |
---|---|---|---|
1W - 실리움 기본 소개 | 1 | published | 2025-07-19 |
1W - 클러스터 세팅 및 cni 마이그레이션 | 2 | published | 2025-07-19 |
1W - 기본 실리움 탐색 및 통신 확인 | 3 | published | 2025-07-19 |
2W - 허블 기반 모니터링 | 4 | published | 2025-07-26 |
2W - 프로메테우스와 그라파나를 활용한 모니터링 | 5 | published | 2025-07-26 |
3W - 실리움 기본 - IPAM | 6 | published | 2025-08-02 |
3W - 실리움 기본 - Routing, Masq, IP Frag | 7 | published | 2025-08-02 |
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve | 8 | published | 2025-08-09 |
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 | 9 | published | 2025-08-09 |
관련 문서
지식 문서, EXPLAIN
이름1 | is-folder | 생성 일자 |
---|---|---|
MetalLB | false | 2025-01-07 16:25 |
기타 문서
Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완이름1 | 코드 | 타입 | 생성 일자 |
---|---|---|---|
T-LoxiLB vs MetalLB | Z3 | topic/temp | 2025-01-06 19:35 |